package com.zxing.practice.config;

import com.zxing.practice.annotation.Anonymous;
import lombok.Getter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.pattern.PathPattern;

import java.util.*;
import java.util.regex.Pattern;

@Configuration
public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware {

    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");

    private ApplicationContext applicationContext;

    @Getter
    private List<String> urls;

    public String ASTERISK = "*";

    public PermitAllUrlProperties(){
        super();
        urls = new ArrayList<>();
    }

    @Override
    public void afterPropertiesSet()
    {
        RequestMappingHandlerMapping mapping = applicationContext.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();

        map.keySet().forEach(info -> {
            PathPatternsRequestCondition pathPatternsCondition = info.getPathPatternsCondition();
            if (pathPatternsCondition != null){
                Set<PathPattern> patterns = pathPatternsCondition.getPatterns();
                HandlerMethod handlerMethod = map.get(info);
                // 获取方法上边的注解 替代path variable 为 *
                Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
                Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(patterns)
                        .forEach(pathPattern -> urls.add(replaceAll(pathPattern.getPatternString(), PATTERN, ASTERISK))));
                // 获取类上边的注解, 替代path variable 为 *
                Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
                Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(patterns)
                        .forEach(pathPattern -> urls.add(replaceAll(pathPattern.getPatternString(), PATTERN, ASTERISK))));
            }
        });
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException{
        this.applicationContext = context;
    }

    private String replaceAll(String text, Pattern regex, String replacement){
        return text == null || regex == null || replacement == null ? text : regex.matcher(text).replaceAll(replacement);
    }
}
